//package com.juyu.miliao.scheduler.service;
//
//import com.juyu.miliao.scheduler.dao.mysql.UserInfoDao;
//import com.juyu.miliao.scheduler.domin.User;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.amqp.rabbit.annotation.RabbitListener;
//import org.springframework.data.redis.core.StringRedisTemplate;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.Resource;
//import java.util.HashMap;
//import java.util.HashSet;
//import java.util.LinkedHashSet;
//import java.util.Map;
//import java.util.Optional;
//import java.util.Set;
//import java.util.concurrent.Callable;
//import java.util.concurrent.locks.Lock;
//import java.util.concurrent.locks.ReadWriteLock;
//import java.util.concurrent.locks.ReentrantReadWriteLock;
//
//import static com.juyu.miliao.scheduler.service.UserListCacheService.JobId.HOT_BOY;
//import static com.juyu.miliao.scheduler.service.UserListCacheService.JobId.HOT_GIRL;
//import static com.juyu.miliao.scheduler.service.UserListCacheService.JobId.NEW_BOY;
//import static com.juyu.miliao.scheduler.service.UserListCacheService.JobId.NEW_GIRL;
//import static java.util.Comparator.comparing;
//import static java.util.stream.Collectors.toCollection;
//import static java.util.stream.Collectors.toList;
//
//@Component
//public class UserListCacheService {
//    private final Logger userListCacheLogger = LoggerFactory.getLogger("userListCache");
//    private final Map<JobId, Callable<Set<Integer>>> jobMap = new HashMap<>();    //保存所有的执行任务
//    private final Map<JobId, Set<Integer>> userIdsSetMap = new HashMap<>();    //保存每个任务最近一次的执行结果
//    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
//    private volatile Map<Integer, Optional<Set<JobId>>> userIdJobIdSetMap = new HashMap<>(); //userIdsSetMap 的倒排序索引，用于快速的匹配
//    @Resource
//    private UserInfoDao userInfoDao;
//    @Resource
//    private StringRedisTemplate stringRedisTemplate;
//
//    public UserListCacheService() {
//        jobMap.put(HOT_BOY, new HotBoyQuartz());
//        jobMap.put(HOT_GIRL, new HotGirlQuartz());
//        jobMap.put(NEW_BOY, new NewBoyQuartz());
//        jobMap.put(NEW_GIRL, new NewGirlQuartz());
//    }
//
//    /**
//     * 监听用户信息的更新，如果更新的用户是缓存中的用户则立刻重置缓存
//     *
//     * @param user
//     */
//    @RabbitListener(queues = "resetUserListCacheQueue")
//    public void updateUser(User user) {
//        userListCacheLogger.info("updateUser:" + user);
//        if (user.getUserId() <= 0) {
//            userListCacheLogger.error("用户参数错误: userId=" + user.getUserId());
//            return;
//        }
//        Lock lock = readWriteLock.readLock();
//        lock.lock();
//        Optional<Set<JobId>> jobIdSet = null;
//        try {
//            jobIdSet = userIdJobIdSetMap.getOrDefault(user.getUserId(), Optional.empty());
//        } finally {
//            lock.unlock();
//        }
//        //如果是缓存中的用户则重置缓存
//        jobIdSet.ifPresent(set -> {
//            set.forEach(jobId -> {
//                executeJob(jobId);
//            });
//        });
//    }
//
//    /**
//     * 定时更新缓存内容
//     */
//    @Scheduled(initialDelay = 1000, fixedDelay = 300000)
//    public void executeSchedulerJob() {
//        try {
//            jobMap.keySet().forEach(jobId -> executeJob(jobId));
//        } catch (Exception e) {
//            userListCacheLogger.error("executeSchedulerJob error:", e);
//        }
//    }
//
//    /**
//     * 根据JobId执行对应的任务
//     *
//     * @param jobId
//     */
//    private void executeJob(JobId jobId) {
//        Lock lock = readWriteLock.writeLock();
//        lock.lock();
//        try {
//            Set<Integer> userIdSet = jobMap.get(jobId).call();
//            updateUserIdUserListMap(jobId, userIdSet);
//        } catch (Exception e) {
//            userListCacheLogger.error("executeJob error: jobId=" + jobId, e);
//        } finally {
//            lock.unlock();
//        }
//    }
//
//    /**
//     * 根据任务的执行结果更新缓存
//     *
//     * @param jobId
//     * @param userIdSet
//     */
//    private void updateUserIdUserListMap(JobId jobId, Set<Integer> userIdSet) {
//        userIdsSetMap.put(jobId, userIdSet);
//        Map<Integer, Optional<Set<JobId>>> tempMap = new HashMap<>();
//        userIdsSetMap.entrySet()
//                .forEach(entry -> {
//                    entry.getValue().forEach(userId -> {
//                        tempMap.computeIfAbsent(userId, key -> Optional.of(new HashSet<>())).get().add(entry.getKey());
//                    });
//                });
//        userIdJobIdSetMap = tempMap;
//        userListCacheLogger.info("updateUserIdUserListMap, jobId=" + jobId + ", userIdSet" + userIdSet);
//    }
//
//    public enum JobId {
//        HOT_BOY,
//        HOT_GIRL,
//        NEW_BOY,
//        NEW_GIRL,
//    }
//
//    private class HotBoyQuartz implements Callable<Set<Integer>> {
//
//        @Override
//        public Set<Integer> call() throws Exception {
//            userListCacheLogger.info("--boy--首页定时任务热门排序查询开始：");
//
//            /** 查询热门 */
//            Set<Integer> collectHot = userInfoDao.getHotSortUserList(1)
//                    .stream()
//                    .sorted(comparing(User::getIsVip).thenComparing(User::getmGradeSum).reversed())
//                    .map(User::getUserId).collect(toCollection(() -> new LinkedHashSet<>()));
//            Set<Integer> userIdSet = stringRedisTemplate.opsForZSet().reverseRange("userDefineSort:hot:boy", 0, -1)
//                    .stream()
//                    .map(Integer::parseInt)
//                    .collect(toCollection(() -> new LinkedHashSet<>()));
//            userIdSet.addAll(collectHot);
//            userIdSet = userIdSet.stream().collect(toCollection(() -> new LinkedHashSet<>()));
//            stringRedisTemplate.delete("bannerSort:hot:boy");
//            if (!userIdSet.isEmpty())
//                stringRedisTemplate.opsForList().rightPushAll("bannerSort:hot:boy", userIdSet.stream().map(String::valueOf).collect(toList()));
//            /** 清除缓存 */
//            for (int j = 1; j < 31; j++) {
//                stringRedisTemplate.delete("bannerCache::" + 1 + "-" + "boy" + "-" + j);
//            }
//            userListCacheLogger.info("--boy--首页定时任务热门排序查询结束：");
//            return userIdSet;
//        }
//
//    }
//
//    private class NewBoyQuartz implements Callable<Set<Integer>> {
//
//        @Override
//        public Set<Integer> call() throws Exception {
//            userListCacheLogger.info("--boy--首页定时任务新人排序查询开始：");
//            /** 查询新人 */
//            Set<Integer> collectNew = userInfoDao.getNewSortUserList(1)
//                    .stream()
//                    .sorted(comparing(User::getIsVip).thenComparing(User::getCreateTime).reversed())
//                    .map(User::getUserId).collect(toCollection(() -> new LinkedHashSet<>()));
//            Set<Integer> userIdSet = stringRedisTemplate.opsForZSet().reverseRange("userDefineSort:new:boy", 0, -1)
//                    .stream()
//                    .map(Integer::parseInt)
//                    .collect(toCollection(() -> new LinkedHashSet<>()));
//            userIdSet.addAll(collectNew);
//            userIdSet = userIdSet.stream().collect(toCollection(() -> new LinkedHashSet<>()));
//            stringRedisTemplate.delete("bannerSort:new:boy");
//            if (!userIdSet.isEmpty())
//                stringRedisTemplate.opsForList().rightPushAll("bannerSort:new:boy", userIdSet.stream().map(String::valueOf).collect(toList()));
//            /** 清除缓存 */
//            for (int j = 1; j < 31; j++) {
//                stringRedisTemplate.delete("bannerCache::" + 2 + "-" + "boy" + "-" + j);
//            }
//            userListCacheLogger.info("--boy--首页定时任务新人排序查询结束：");
//            return userIdSet;
//        }
//
//    }
//
//    private class HotGirlQuartz implements Callable<Set<Integer>> {
//
//        @Override
//        public Set<Integer> call() throws Exception {
//            userListCacheLogger.info("--girl--首页定时任务热门排序查询开始：");
//            /** 查询热门 */
//            Set<Integer> collectHot = userInfoDao.getHotSortUserList(2)
//                    .stream()
//                    .sorted(comparing(User::getIsVip).thenComparing(User::getmGradeSum).reversed())
//                    .map(User::getUserId).collect(toCollection(() -> new LinkedHashSet<>()));
//            Set<Integer> userIdSet = stringRedisTemplate.opsForZSet().reverseRange("userDefineSort:hot:girl", 0, -1)
//                    .stream()
//                    .map(Integer::parseInt)
//                    .collect(toCollection(() -> new LinkedHashSet<>()));
//            userIdSet.addAll(collectHot);
//            userIdSet = userIdSet.stream().collect(toCollection(() -> new LinkedHashSet<>()));
//            stringRedisTemplate.delete("bannerSort:hot:girl");
//            if (!userIdSet.isEmpty())
//                stringRedisTemplate.opsForList().rightPushAll("bannerSort:hot:girl", userIdSet.stream().map(String::valueOf).collect(toList()));
//            /** 清除缓存 */
//            for (int j = 1; j < 31; j++) {
//                stringRedisTemplate.delete("bannerCache::" + 1 + "-" + "girl" + "-" + j);
//            }
//            userListCacheLogger.info("--girl--首页定时任务热门排序查询结束：");
//            return userIdSet;
//        }
//
//    }
//
//    private class NewGirlQuartz implements Callable<Set<Integer>> {
//
//        @Override
//        public Set<Integer> call() throws Exception {
//            userListCacheLogger.info("--girl--首页定时任务新人排序查询开始：");
//            /** 查询新人 */
//            Set<Integer> collectNew = userInfoDao.getNewSortUserList(2)
//                    .stream()
//                    .sorted(comparing(User::getIsVip).thenComparing(User::getCreateTime).reversed())
//                    .map(User::getUserId).collect(toCollection(() -> new LinkedHashSet<>()));
//            Set<Integer> userIdSet = stringRedisTemplate.opsForZSet().reverseRange("userDefineSort:new:girl", 0, -1)
//                    .stream()
//                    .map(Integer::parseInt)
//                    .collect(toCollection(() -> new LinkedHashSet<>()));
//            userIdSet.addAll(collectNew);
//            userIdSet = userIdSet.stream().collect(toCollection(() -> new LinkedHashSet<>()));
//            stringRedisTemplate.delete("bannerSort:new:girl");
//            if (!userIdSet.isEmpty())
//                stringRedisTemplate.opsForList().rightPushAll("bannerSort:new:girl", userIdSet.stream().map(String::valueOf).collect(toList()));
//            /** 清除缓存 */
//            for (int j = 1; j < 31; j++) {
//                stringRedisTemplate.delete("bannerCache::" + 2 + "-" + "girl" + "-" + j);
//            }
//            userListCacheLogger.info("--girl--首页定时任务新人排序查询结束：");
//            return userIdSet;
//        }
//    }
//
//}
